 /*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is OntoLing.
 *
 * The Initial Developer of the Original Code is University of Roma Tor Vergata.
 * Portions created by University of Roma Tor Vergata are Copyright (C) 2004.
 * All Rights Reserved.
 *
 * OntoLing was developed by the Artificial Intelligence Research Group
 * (ai-nlp.info.uniroma2.it) at the University of Roma Tor Vergata
 * Current information about OntoLing can be obtained at 
 * http//ai-nlp.info.uniroma2.it/software/OntoLing.html
 *
 */

 /*
  * Contributor(s): Armando Stellato stellato@info.uniroma2.it
 */

/*
 * GUI_Facade.java
 *
 * Created on 31 marzo 2004, 15.41
 */

package it.uniroma2.art.ontoling.protege.ui;


import it.uniroma2.art.lw.model.objects.LinguisticInterface;
import it.uniroma2.art.lw.model.objects.MatchCaseToggling;
import it.uniroma2.art.lw.model.objects.SearchFilter;
import it.uniroma2.art.lw.model.objects.SearchWord;
import it.uniroma2.art.lw.model.objects.WholeWordToggling;
import it.uniroma2.art.ontoling.OntoLingCore;
import it.uniroma2.art.ontoling.exceptions.UIActionException;
import it.uniroma2.art.ontoling.protege.util.PseudoLogger;
import it.uniroma2.art.ontoling.protege.util.Util;
import it.uniroma2.art.ontoling.ui.GUIAdapter;
import it.uniroma2.art.ontoling.ui.UIActionList;
import it.uniroma2.art.ontoling.ui.UIReasoner;
import it.uniroma2.art.ontoling.ui.UIAction.GlossTextSetter;
import it.uniroma2.art.ontoling.ui.UIAction.SemanticIndexTextSetter;

import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.stanford.smi.protege.model.Frame;
import edu.stanford.smi.protege.model.KnowledgeBase;
import edu.stanford.smi.protege.model.Slot;
import edu.stanford.smi.protegex.owl.model.RDFResource;
import edu.stanford.smi.protegex.owl.model.impl.DefaultRDFProperty;
import edu.stanford.smi.protegex.owl.model.impl.OWLUtil;

/**
 * @author  Armando Stellato <stellato@info.uniroma2.it>
 */

public class GUI_Facade {

    //public int resultsTablecolumns;
    
    private LinguisticInterface lInt;
    private Linguistic_GUI lGUI;
    private UIReasoner uiReasoner;
    private ProtegeGUIAdapter guiAdapter;
    
    public Method notifiedFrameTermInsertion;
    public Method notifiedFrameGlossInsertion;
    public Method notifiedFrameSenseIdInsertion;

    protected static Log logger = LogFactory.getLog(GUI_Facade.class);
    
    private static GUI_Facade gui_Facade;
    
    private GUI_Facade(){}
    
    public static GUI_Facade getInstance(){
    	if(gui_Facade == null) {
    		gui_Facade = new GUI_Facade();
    	}
    	return gui_Facade;
    }
    
    public void initialize_GUI(LinguisticInterface LInst)
    {        
    	//resultsTablecolumns = ((ResultsTableModel)GUI_Manager.getLinguisticGUI().ResultsTable.getModel()).getColumnCount();
        lInt = LInst;
        lGUI = GUI_Manager.getLinguisticGUI();
        uiReasoner = OntoLingCore.getOntoLingCore().getUIReasoner();
        guiAdapter = new ProtegeGUIAdapter();
        OntoLingCore.getOntoLingCore().setGUIAdapter(guiAdapter);
        //String linstClassName = LInst.getClass().toString();
        
        //Relations ComboBoxes DEACTIVATION of listeners
        deactivateRelationBoxListeners();
        
        UIActionList al = uiReasoner.initialize(lInt);
        guiAdapter.handleUIActionList(al);
        
        activateRelationBoxListeners();     
        
    }       
    
    //TODO move these methods as implementation of a series of interface methods of OntoLing core, like addGloss, addSemanticIndex, addLabel, for ontology concepts
    public void initializeMethods_on_KBChange(KnowledgeBase kb) throws ClassNotFoundException, SecurityException, NoSuchMethodException {
        
        //Class<?> thisClass = it.uniroma2.art.ontoling.ui.UIReasoner.class 
        Class<?> thisClass = GUI_Facade.class;
        Class<?>[] parameterTypes; //TODO may be removed if using java Tiger, passing no parameters to getMethod
        String method;    
        
        //choose proper notifiedFrameTermInsertion
        parameterTypes = new Class[2];
        parameterTypes[0] =  edu.stanford.smi.protege.model.Frame.class;
        parameterTypes[1] =  Class.forName("[Ljava.lang.String;");
        if (Util.kbInOWL(kb))
            method = "notifiedFrameTermInsertion_OWL";
        else method = "notifiedFrameTermInsertion_SP";
        notifiedFrameTermInsertion = thisClass.getMethod(method, parameterTypes);    

        //choose proper notifiedFrameGlossInsertion
        parameterTypes = new Class[2];
        parameterTypes[0] = edu.stanford.smi.protege.model.Frame.class;  
        parameterTypes[1] = java.lang.String.class;
        if (Util.kbInOWL(kb))
            method = "notifiedFrameGlossInsertion_OWL";
        else method = "notifiedFrameGlossInsertion_SP";
        notifiedFrameGlossInsertion = thisClass.getMethod(method, parameterTypes);             

        //choose proper notifiedFrameSenseIdInsertion
        parameterTypes = new Class[1];
        parameterTypes[0] =  edu.stanford.smi.protege.model.Frame.class;
        if (Util.kbInOWL(kb))
            method = "notifiedFrameSenseIdInsertion_OWL";
        else method = "notifiedFrameSenseIdInsertion_SP";
        notifiedFrameSenseIdInsertion = thisClass.getMethod(method, parameterTypes);           
    }
    
    
    public void initializeListeners() {
        
        lGUI.StringSearchTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	notifiedSearchField();
            }
        });
        
        
        lGUI.ConceptTField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                conceptTFieldActionPerformed(evt);
            }
        });
        
        
        lGUI.SynonymsList.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                doubleclickonTerm(evt);
            }
        });
        
        lGUI.ResultsTable.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                if (evt.getClickCount() == 1){
                    notifiedSelectedRowOnResultsTable(getSelectedEntryFromResultTable(), getSelectedWordFromResultTable());
                }
            }
        });
        
        lGUI.ResultsTable.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent ke) {  
                int kc = ke.getKeyCode();
                if (kc == KeyEvent.VK_SPACE) {
                	try { 
                		UIActionList al = uiReasoner.notifiedSelectedRowOnResultsTable( getSelectedEntryFromResultTable(), 
                			getSelectedWordFromResultTable() );
                		guiAdapter.handleUIActionList(al);
                		}
                    catch(UIActionException e) { showErrorMessage(e); }
                }
            }   
        });
    }
    
    
   public void activateRelationBoxListeners() {
        
        lGUI.CRelFindCBx.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                semanticRelFindCBxActionPerformed();
            }
        });
        
        lGUI.LRelFindCBx.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lexicalRelFindCBxActionPerformed();
            }
        });       
        
        /*
        lGUI.SearchStrategyCBx.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                searchStrategyCBxActionPerformed();
            }
        });
        */    
   }
    
   public void deactivateRelationBoxListeners() {
       
       ActionListener [] actls = lGUI.CRelFindCBx.getActionListeners();
       for(int i=0;i<actls.length;i++)
           lGUI.CRelFindCBx.removeActionListener(actls[i]);
       
       actls = lGUI.LRelFindCBx.getActionListeners();
       for(int i=0;i<actls.length;i++)
           lGUI.LRelFindCBx.removeActionListener(actls[i]);
       
       actls = lGUI.SearchStrategyCBx.getActionListeners();
       for(int i=0;i<actls.length;i++)
           lGUI.SearchStrategyCBx.removeActionListener(actls[i]);
   }
    

   //LISTENERS
   
   private void semanticRelFindCBxActionPerformed() {
       try {
    	   if(getSelectedSemex() == null)
    		   return;
           UIActionList al = uiReasoner.notifiedSemanticRelation(getSelectedSemex(), getSelectedSemanticRelation());
           guiAdapter.handleUIActionList(al);           
       } catch (UIActionException e) {
           showErrorMessage(e);
       }
   } 
   
   
   private void lexicalRelFindCBxActionPerformed() {
       try {
    	   if(getSelectedWord() == null || getSelectedSemex() == null)
    		   return;
    	   UIActionList al = uiReasoner.notifiedLexicalRelation(getSelectedWord(), getSelectedSemex(), getSelectedLexicalRelation());
           guiAdapter.handleUIActionList(al);           
       } catch (UIActionException e) {
           showErrorMessage(e);
       }
   }

   private void searchStrategyCBxActionPerformed() {
       try {
           UIActionList al = uiReasoner.notifiedSearchStrategy(getSearchWord(), getSelectedSearchStrategy(), getSelectedSearchFilter());
           guiAdapter.handleUIActionList(al);
       } catch (UIActionException e) {
           showErrorMessage(e);
       }
   }
   
   void notifiedSearchField() {
       try {
    	   UIActionList al = uiReasoner.notifiedSearchField(getSearchWord(), getSelectedSearchStrategy(), getSelectedSearchFilter());
           guiAdapter.handleUIActionList(al);
           
           //SearchWord searchWord = guiAdapter.getSearchWord();
           //al = uiReasoner.notifiedSearchWord(searchWord);
           //guiAdapter.handleUIActionList(al);
           
       } catch (UIActionException e) {
           showErrorMessage(e);
       }    
   }

   public void notifiedSelectedRowOnResultsTable(String entry, String word) {
       try { 
           UIActionList al = uiReasoner.notifiedSelectedRowOnResultsTable(entry, word);
           guiAdapter.handleUIActionList(al);
       }
       catch(UIActionException e) { showErrorMessage(e); }
   }
   
   
   private void doubleclickonTerm(java.awt.event.MouseEvent evt) {
       if (evt.getClickCount() == 2){
           String term = (String)lGUI.SynonymsList.getSelectedValue();
           try {
            UIActionList al = uiReasoner.notifiedDblClkOnSynonymsTable(term);
            guiAdapter.handleUIActionList(al);
        } catch (UIActionException e) {
            showErrorMessage(e);
        }
       }        
   }
 
   
   private void conceptTFieldActionPerformed(java.awt.event.ActionEvent evt) {
       try {
           UIActionList al = uiReasoner.notifiedSearchConcept(((javax.swing.JTextField)evt.getSource()).getText());
           guiAdapter.handleUIActionList(al);
       } catch (UIActionException e) {
           showErrorMessage(e);
       }
   }
   
   

   public void notifiedFrameTermInsertion(Frame frm) {
        String[] selTerms = getSelectedWords();
        Object[] parameters = {frm, selTerms};
        try {
            notifiedFrameTermInsertion.invoke(this,parameters);
        } catch (Exception e) {
            showErrorMessage("unavailable Method", "", e);
        }     
    }    
    
    public void notifiedFrameTermInsertion(Frame frm, String[] labels) {
        Object[] parameters = {frm, labels};
        try {
            notifiedFrameTermInsertion.invoke(this,parameters);
        } catch (Exception e) {
            //showErrorMessage("unavailable Method", "", e); // TODO check why this method in Protege 3.4.8 gives an exception while before it didn't
        }     
    }

    public void notifiedFrameSenseIdInsertion(Frame frm) {
        Object[] parameters = {frm};     
        try {
            notifiedFrameSenseIdInsertion.invoke(this,parameters);
        } catch (Exception e) {
            showErrorMessage("unavailable Method", "", e);
        }        
    }    
    
    
    public void notifiedFrameGlossInsertion(Frame frm) {
        String description = getDescription();
        Object[] parameters = {frm, description};     
        try {
        	notifiedFrameGlossInsertion.invoke(this,parameters);
        } catch (Exception e) {
            showErrorMessage("unavailable Method", "", e);
        }     
    }

    public void notifiedFrameGlossInsertion(Frame frm, String gloss) {
        Object[] parameters = {frm, gloss};     
        try {
            notifiedFrameGlossInsertion.invoke(this,parameters);
        } catch (Exception e) {
            showErrorMessage("unavailable Method", "", e);
        }     
    }    
    
    //IMPLEMENTED METHODS
    
    // notifiedFrameTermInsertion
    public void notifiedFrameTermInsertion_OWL(Frame frm, String[] labels) {   
    	 for(int i=0;i<labels.length;i++)
             OWLUtil.addLabel((RDFResource) frm, labels[i], lInt.getLanguage());
        /*Slot terminology = GUI_Manager.getOntologyPanel().getTerminologySlot();
        if (((DefaultRDFProperty)terminology).isAnnotationProperty()) {
            for(int i=0;i<labels.length;i++)
                OWLUtil.addLabel((RDFResource) frm, labels[i], lInt.getLanguage());
        }
        else {
            for(int i=0;i<labels.length;i++)
                frm.addOwnSlotValue(terminology, labels[i]);            
        }*/
    }
    
    public void notifiedFrameTermInsertion_SP(Frame frm, String[] labels) {
    	Slot terminology = GUI_Manager.getOntologyPanel().getTerminologySlot();
        Collection frameSynonyms = frm.getOwnSlotValues(terminology);
        for(int i=0;i<labels.length;i++)
            //if controllare che non ci sia gi� il sinonimo. Usare il vettore di sopra.
            if (!frameSynonyms.contains(labels[i])){
                frm.addOwnSlotValue(terminology, labels[i]);
            }
    }       

    
    // notifiedFrameSenseIdInsertion    
    public void notifiedFrameSenseIdInsertion_OWL(Frame frm) {
        String senseId = getSelectedSemex(); 
        OWLUtil.addLabel((RDFResource) frm, senseId, lInt.getResourceShortId());
        /*Slot terminology = GUI_Manager.getOntologyPanel().getTerminologySlot();
        if (((DefaultRDFProperty)terminology).isAnnotationProperty())
            OWLUtil.addLabel((RDFResource) frm, senseId, lInt.getResourceShortId());
        else
            frm.addOwnSlotValue(terminology, senseId);*/            
    }
    
    public void notifiedFrameSenseIdInsertion_SP(Frame frm) {
        String senseId = getSelectedSemex();
        Slot terminology = GUI_Manager.getOntologyPanel().getTerminologySlot();
        frm.addOwnSlotValue(terminology, senseId);    }         
    
    
    // notifiedFrameGlossInsertion    
    public void notifiedFrameGlossInsertion_OWL(Frame frm, String gloss) {
        Slot terminology = GUI_Manager.getOntologyPanel().getTerminologySlot();
        if(gloss != null)
        	OWLUtil.addComment((RDFResource) frm, gloss);
    }
    
    public void notifiedFrameGlossInsertion_SP(Frame frm, String gloss) {
    	Slot terminology = GUI_Manager.getOntologyPanel().getTerminologySlot();
    	if(gloss != null)
    		frm.setDocumentation(gloss);
    }     
    
    
    
    //UI SETTERS
    
    public void setSearchFieldText(String txt) { 
        lGUI.StringSearchTextField.setText(txt);
    }
    
    public void setGlossAreaText(String txt) {
        lGUI.DescriptionField.setText(txt);
    }

    public void setSemanticIndexFieldText(String txt) {
        lGUI.ConceptTField.setText(txt);
    }
    
    public void setSynonymsList(List<String> synonyms, String selWord) {
        DefaultListModel synonymsList = (DefaultListModel)lGUI.SynonymsList.getModel();
        synonymsList.clear();
        if (synonyms!=null){
            for (String synonym : synonyms){            
                synonymsList.addElement(synonym);
                
            }
            if(selWord != null){
            	String selWordAdjusted = selWord.replace(" ", "_");
            	for(int pos = 0; pos < synonyms.size(); ++pos){
            		if(synonyms.get(pos).compareToIgnoreCase(selWordAdjusted) == 0){
            			lGUI.SynonymsList.setSelectedIndex(pos);
            		}
            		
            	}
            }
            	
        }
    }
    
    public void setResultTable(ArrayList<String[]> results) {
        ResultsTableModel resultsTableModel = ((ResultsTableModel)lGUI.ResultsTable.getModel());
        resultsTableModel.clear();
        for (String[] result : results)
            resultsTableModel.addRow( result );        
    }
    
   
    public void setEnableStatusMatchCaseCBx(boolean status, String tooltTipMsg)
    {
        //JCheckBox CBx = lGUI.MatchCaseCBx;
    	//CBx.setEnabled(status);
    	//CBx.setToolTipText(tooltTipMsg);
    }

    public void setEnableStatusWholeWordCBx(boolean status, String tooltTipMsg)
    {
    	//JCheckBox CBx = GUI_Manager.getLinguisticGUI().WholeWordCBx;
    	//CBx.setEnabled(status);
    	//CBx.setToolTipText(tooltTipMsg);
    }
    
    public void setMatchCaseStatus(boolean status)
    {
        ((MatchCaseToggling)lInt).setMatchCaseSearchStatus(status);
    }

    public void setWholeWordStatus(boolean status)
    {
        ((WholeWordToggling)lInt).setWholeWordSearchStatus(status);
    }    
    
    
    
    
    //UI GETTERS
   
    
    private String getSearchWord() {
        return lGUI.StringSearchTextField.getText();
    }
    
    String getSelectedSemex() {
        String sense = lGUI.ConceptTField.getText();
        if (!sense.equals(""))
            return sense;
        else return null;
    }
    
    String getSelectedWord()
    {
        return (String)GUI_Manager.getLinguisticGUI().SynonymsList.getSelectedValue();
    }

    private String [] getSelectedWords()
    {
        Object [] termsobj = GUI_Manager.getLinguisticGUI().SynonymsList.getSelectedValues();
        String [] terms = new String[termsobj.length];
        for (int i=0;i<termsobj.length;i++)
            terms[i] = (String)termsobj[i]; 
        return terms;
    }    
    
    String getDescription()
    {
        return (String)GUI_Manager.getLinguisticGUI().DescriptionField.getText();
    }    
    
    public String getSelectedSemanticRelation() {
        return (String)lGUI.CRelFindCBx.getSelectedItem();
    }
    
    public String getSelectedLexicalRelation() {
        return (String)lGUI.LRelFindCBx.getSelectedItem();
    }
    
    public String getSelectedSearchStrategy() {
        return (String)lGUI.SearchStrategyCBx.getSelectedItem();
    }
    
    public String getSelectedEntryFromResultTable() {
        return (String)lGUI.ResultsTable.getModel().getValueAt(lGUI.ResultsTable.getSelectedRow(), 0);
    }
    
    public String getSelectedWordFromResultTable() {
        return (String)lGUI.ResultsTable.getModel().getValueAt(lGUI.ResultsTable.getSelectedRow(), 1);
    }
    
    public SearchFilter[] getSelectedSearchFilter(){
    	ArrayList <SearchFilter>searchFilters = new ArrayList<SearchFilter>();
    	SearchFilter[] searchFiltersArray;
    	SearchFilter searchFilter;
    	String appoggio="";
    	for(String key : lGUI.filterBoxMapState.keySet() ){
    		if(lGUI.filterBoxMapState.get(key)){
    			appoggio+=key+"\t";
    			searchFilter = new SearchFilter(key);
    			searchFilters.add(searchFilter);
    		}
    	}
    	searchFiltersArray = new SearchFilter[searchFilters.size()];
    	searchFiltersArray = searchFilters.toArray(searchFiltersArray);
    	return searchFiltersArray;
    	
    }
    
    //UTILITIES
    
    
    public void showErrorMessage(UIActionException e) {
        showErrorMessage(e.getTitle(), e.getMessage(), e.getCause());
    }
    
    public void showErrorMessage(String title, String firstPart, Throwable e) {
        String errorMsg = firstPart + "\n" + e.getMessage() + "\n" + e;                      
        java.awt.Frame frame = JOptionPane.getRootFrame();
        JOptionPane.showMessageDialog(frame, errorMsg, title, JOptionPane.ERROR_MESSAGE);
        logger.error(e.getMessage(), e);
    }
    

    
    
}    

